home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Taifun / Taifun 099 (1989-05-15)(Ossowski, Stefan)(DE)(PD).zip / Taifun 099 (1989-05-15)(Ossowski, Stefan)(DE)(PD).adf / PCQ / Source / Utilities.p < prev   
Text File  |  1989-03-31  |  10KB  |  453 lines

  1. external;
  2.  
  3. {
  4.     Utilities.p (of PCQ Pascal)
  5.     Copyright (c) 1989 Patrick Quaid.
  6.  
  7.     This module handles the various tables and whatever
  8. run-time business the compiler might have.
  9. }
  10.  
  11. const
  12. {$I "pasconst.i"}
  13.  
  14. type
  15. {$I "pastype.i"}
  16.  
  17. var
  18. {$I "pasvar.i"}
  19.  
  20.     procedure error(s : string);
  21.         forward;
  22.     function streq(s1, s2 : string) : boolean;
  23.         forward;
  24.     function strcmp(s1, s2 : string) : integer;
  25.         forward;
  26.     procedure nextsymbol;
  27.         forward;
  28.  
  29. function basetype(orgtype : integer): integer;
  30.  
  31. {
  32.     This routine returns the base type of type.  If this
  33. routine is used consistently, ranges and subtypes will work with
  34. some consistency.
  35. }
  36.  
  37. begin
  38.     while (idents[orgtype].offset = vsubrange) or
  39.       (idents[orgtype].offset = vsynonym) do
  40.     orgtype := idents[orgtype].vtype;
  41.     basetype := orgtype;
  42. end;
  43.  
  44. function highertype(typea, typeb : integer): integer;
  45.  
  46. {
  47.     This routine returns the more complex type of the two
  48. numeric types passed to it.  In other words a 32 bit integer is
  49. 'higher' than a 16 bit one.  When real numbers get in the language,
  50. floating point will be the most complex numeric type.
  51. }
  52.  
  53. begin
  54.     if (typea = inttype) or (typeb = inttype) then
  55.     highertype := inttype;
  56.     if (typea = shorttype) or (typeb = shorttype) then
  57.     highertype := shorttype;
  58.     highertype := typea;
  59. end;
  60.  
  61. procedure promotetype(var from : integer; other : integer; reg : integer);
  62.  
  63. {
  64.     This routine extends reg as necessary to make the 'from'
  65. type equivalent to 'other'.  Again, when real numbers are
  66. implemented this will also be responsible for converting the reg to
  67. FFP format.
  68. }
  69.  
  70. var
  71.     totype : integer;
  72. begin
  73.     from := basetype(from);
  74.     other := basetype(other);
  75.     totype := highertype(from, other);
  76.     if from = totype then
  77.     return;
  78.     if totype = inttype then begin
  79.     if from = shorttype then
  80.         writeln(output, "\text.l\td", reg)
  81.     else if from = bytetype then begin
  82.         writeln(output, "\text.w\td", reg);
  83.         writeln(output, "\text.l\td", reg);
  84.     end;
  85.     from := inttype;
  86.     end else if totype = shorttype then begin
  87.     if from = bytetype then
  88.         writeln(output, "\text.w\td", reg);
  89.     from := shorttype;
  90.     end;
  91. end;
  92.  
  93. function match(sym : integer): boolean;
  94.  
  95. {
  96.     If the current symbol is sym, return true and get the
  97. next one.
  98. }
  99.  
  100. begin
  101.     if currsym = sym then begin
  102.     nextsymbol;
  103.     match := true;
  104.     end else
  105.     match := false;
  106. end;
  107.  
  108. {
  109.     The following routines just print out common error messages
  110. and make some common tests.
  111. }
  112.  
  113. procedure mismatch;
  114. begin
  115.     error("Mismatched types");
  116. end;
  117.  
  118. procedure neednumber;
  119. begin
  120.     error("Need a numeric type");
  121. end;
  122.  
  123. procedure noleftparent;
  124. begin
  125.     error("No left parenthesis");
  126. end;
  127.  
  128. procedure norightparent;
  129. begin
  130.     error("No right parenthesis");
  131. end;
  132.  
  133. procedure needleftparent;
  134. begin
  135.     if not match(leftparent1) then
  136.     noleftparent;
  137. end;
  138.  
  139. procedure needrightparent;
  140. begin
  141.     if not match(rightparent1) then
  142.     norightparent;
  143. end;
  144.  
  145. procedure enterspell(str : string);
  146.  
  147. {
  148.     This enters the string into the spelling table.
  149. }
  150.  
  151. begin
  152.     while str^ <> chr(0) do begin
  153.     spelling[spellptr] := str^;
  154.     str := string(integer(str) + 1);
  155.     spellptr := spellptr + 1;
  156.     end;
  157.     spelling[spellptr] := chr(0);
  158.     spellptr := spellptr + 1;
  159. end;
  160.  
  161. function enterstandard(stobject, stoffset, sttype, stupper, stlower,
  162.             stsize, stindtype : integer) : integer;
  163.  
  164. {
  165.     This just adds the appropriate record to the array.  It
  166. gets its name because it was originally used to add standard procs
  167. and funcs, but in fact in can be used for just about anything.
  168. }
  169.  
  170. begin
  171.     idents[identptr].name := string(integer(adr(spelling)) + spellptr - 1);
  172.     idents[identptr].object  := stobject;
  173.     idents[identptr].offset  := stoffset;
  174.     idents[identptr].vtype   := sttype;
  175.     idents[identptr].upper   := stupper;
  176.     idents[identptr].lower   := stlower;
  177.     idents[identptr].size    := stsize;
  178.     idents[identptr].indtype := stindtype;
  179.     identptr := identptr + 1;
  180.     enterstandard := identptr - 1;
  181. end;
  182.  
  183. procedure ns;
  184.  
  185. {
  186.     This routine just tests for a semicolon.
  187. }
  188.  
  189. begin
  190.     if not match(semicolon1) then begin
  191.     if (currsym <> end1) and (currsym <> else1) and (currsym <> until1) then
  192.         error("missing semicolon");
  193.     end else
  194.     while match(semicolon1) do;
  195. end;
  196.  
  197. function typecmp(typea, typeb : integer) : boolean;
  198.  
  199. {
  200.     This routine just compares two types to see if they're
  201. equivalent.  Subranges of the same type are considered equivalent.
  202. Note that 'badtype' is actually a universal type used when there
  203. are errors, in order to avoid streams of errors.
  204. }
  205.  
  206. var
  207.     t1ptr,
  208.     t2ptr  : integer;
  209. begin
  210.     typea := basetype(typea);
  211.     typeb := basetype(typeb);
  212.  
  213.     if typea = typeb then
  214.     typecmp := true;
  215.     if (typea = badtype) or (typeb = badtype) then
  216.     typecmp := true;
  217.     if idents[typea].offset <> idents[typeb].offset then
  218.     typecmp := false;
  219.     if idents[typea].size <> idents[typeb].size then
  220.     typecmp := false;
  221.     if idents[typea].offset = varray then begin
  222.     if (idents[typea].upper - idents[typea].lower) <>
  223.        (idents[typeb].upper - idents[typeb].lower) then
  224.         typecmp := false;
  225.     typecmp := typecmp(idents[typea].vtype, idents[typeb].vtype);
  226.     end;
  227.     if idents[typea].offset = vpointer then
  228.     typecmp := typecmp(idents[typea].vtype, idents[typeb].vtype);
  229.     if idents[typea].offset = vfile then
  230.     typecmp := typecmp(idents[typea].vtype, idents[typeb].vtype);
  231.     if idents[typea].offset = vrecord then begin
  232.     t1ptr := idents[typea].indtype;
  233.     t2ptr := idents[typeb].indtype;
  234.     while (t1ptr <> 0) and (t2ptr <> 0) do begin
  235.         if not typecmp(idents[t1ptr].vtype, idents[t2ptr].vtype) then
  236.         typecmp := false;
  237.         t1ptr := idents[t1ptr].indtype;
  238.         t2ptr := idents[t2ptr].indtype;
  239.     end;
  240.     typecmp := t1ptr = t2ptr;
  241.     end;
  242.     if (idents[typea].offset = vordinal) and
  243.     (idents[typea].indtype <> 0) then begin
  244.     t1ptr := idents[typea].indtype;
  245.     t2ptr := idents[typeb].indtype;
  246.     while (t1ptr <> 0) and (t2ptr <> 0) do begin
  247.         if not streq(idents[t1ptr].name, idents[t2ptr].name) then
  248.         typecmp := false;
  249.         t1ptr := idents[t1ptr].indtype;
  250.         t2ptr := idents[t2ptr].indtype;
  251.     end;
  252.     typecmp := t1ptr = t2ptr;
  253.     end;
  254.     typecmp := false;
  255. end;
  256.  
  257. function numbertype(testtype : integer) : boolean;
  258.  
  259. {
  260.     Return true if this is a numeric type.
  261. }
  262.  
  263. begin
  264.     testtype := basetype(testtype);
  265.     if testtype = inttype then
  266.     numbertype := true
  267.     else if testtype = shorttype then
  268.     numbertype := true
  269.     else if testtype = bytetype then
  270.     numbertype := true;
  271.     numbertype := false;
  272. end;
  273.  
  274. function typecheck(typea, typeb : integer) : boolean;
  275.  
  276. {
  277.     This is similar to typecmp, but considers numeric types
  278. equivalent.
  279. }
  280.  
  281. begin
  282.     if (idents[typea].object = obtype) and
  283.     (idents[typeb].object = obtype) then begin
  284.     typea := basetype(typea);
  285.     typeb := basetype(typeb);
  286.     if typea = typeb then
  287.         typecheck := true;
  288.     if numbertype(typea) and numbertype(typeb) then
  289.         typecheck := true;
  290.     typecheck := typecmp(typea, typeb);
  291.    end else
  292.     typecheck := false;
  293. end;
  294.  
  295. function addtype(typoff, typtype, typup, typlow,
  296.             typsize, typind : integer) : integer;
  297.  
  298. {
  299.     Adds a type to the id array.
  300. }
  301.  
  302. var
  303.     index    : integer;
  304.     found    : boolean;
  305. begin
  306.     idents[identptr].name    := string(adr(spelling));
  307.     idents[identptr].object  := obtype;
  308.     idents[identptr].offset  := typoff;
  309.     idents[identptr].vtype   := typtype;
  310.     idents[identptr].upper   := typup;
  311.     idents[identptr].lower   := typlow;
  312.     idents[identptr].size    := typsize;
  313.     idents[identptr].indtype := typind;
  314.  
  315.     identptr := identptr + 1;
  316.     addtype := identptr - 1;
  317. end;
  318.  
  319. function findid(idname : string): integer;
  320.  
  321. {
  322.     This finds the index whose 'name' field is the same as
  323. idname, or zero if it doesn't find it.  Note that this searches
  324. backwards, in order to properly do scopes.  It will run into the
  325. most local identifiers first.
  326.     I once thought about implementing case sensitivity through
  327. a compiler directive.  It would have been fairly simple, actually:
  328. just use separate routines in place of streq and strcmp in the
  329. following routines.  These new routines should be case sensitive,
  330. of course.
  331. }
  332.  
  333. var
  334.     index    : integer;
  335. begin
  336.     index := identptr - 1;
  337.     while index > 0 do begin
  338.     if streq(idname, idents[index].name) then
  339.         findid := index;
  340.     index := index - 1;
  341.     end;
  342.     findid := 0;
  343. end;
  344.  
  345. function checkid(idname : string; startspot : integer): integer;
  346.  
  347. {
  348.     This is like the above, but only checks as far back as
  349. startspot in order to implement scopes.  This is used to make sure
  350. there are no identifiers with the same name under the same scope.
  351. }
  352.  
  353. var
  354.     index    : integer;
  355. begin
  356.     index := startspot;
  357.     while index < identptr do begin
  358.     if idents[index].object <> field then
  359.         if streq(idname, idents[index].name) then
  360.         checkid := index;
  361.     index := index + 1;
  362.     end;
  363.     checkid := 0;
  364. end;
  365.  
  366. function findfield(idname : string; startspot : integer) : integer;
  367.  
  368. {
  369.     This just finds the appropriate field, given the index of
  370. the record type.
  371. }
  372.  
  373. var
  374.     index    : integer;
  375. begin
  376.     index := idents[startspot].indtype;
  377.     while index <> 0 do begin
  378.     if streq(idname, idents[index].name) then
  379.         findfield := index;
  380.     index := idents[index].indtype;
  381.     end;
  382.     findfield := 0;
  383. end;
  384.  
  385. function searchreserved() : integer;
  386.  
  387. {
  388.     This just does a binary chop search of the list of reserved
  389. words.
  390. }
  391.  
  392. var
  393.     top        : integer;
  394.     middle    : integer;
  395.     bottom    : integer;
  396.     compare    : integer;
  397. begin
  398.     bottom := 1;
  399.     top := lastreserved;
  400.     while bottom <= top do begin
  401.     middle := (bottom + top) div 2;
  402.     compare := strcmp(reserved[middle], symtext);
  403.     if compare = 0 then
  404.         searchreserved := middle
  405.     else if compare < 0 then
  406.         bottom := middle + 1
  407.     else
  408.         top := middle - 1;
  409.     end;
  410.     searchreserved := 0;
  411. end;
  412.  
  413. function isvariable(index : integer) : boolean;
  414.  
  415. {
  416.     Returns true if index is a variable.
  417. }
  418.  
  419. var
  420.     what    : integer;
  421. begin
  422.     what := idents[index].object;
  423.     if what = local then
  424.     isvariable := true
  425.     else if what = refarg then
  426.     isvariable := true
  427.     else if what = valarg then
  428.     isvariable := true
  429.     else if what = global then
  430.     isvariable := true
  431.     else
  432.     isvariable := false;
  433. end;
  434.  
  435. function suffix(size : integer): char;
  436.  
  437. {
  438.     Returns the proper assembly language suffix for the various
  439. operations.
  440. }
  441.  
  442. begin
  443.     if size = 1 then
  444.     suffix := 'b'
  445.     else if size = 2 then
  446.     suffix := 'w'
  447.     else if size = 4 then
  448.     suffix := 'l'
  449.     else {must be a bug!}
  450.     suffix := '!';
  451. end;
  452.  
  453.